/************************************************************************
Copyright (c) 2010, 2013, C.R. All rights reserved. 

E-mail: crtoyou@gmail.com; crtoyou@163.com

You can redistribute it and/or modify it under the terms of the
GNU Lesser General Public License as published by the
Free Software Foundation version 3 of the License.

This source code is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program. if not, write to the Free Software Foundation, Inc., 
51 Franklin St, Fifth Floor, Boston, MA 02110-1301  USA
************************************************************************/

#ifndef __CR_SYNC_OBJECT_LOCK_H__
#define __CR_SYNC_OBJECT_LOCK_H__

#include <Windows.h>
#include <crdebug.h>

namespace cr {

class critical_section 
{
public:
	critical_section(){InitializeCriticalSection(&sync);}
	~critical_section(){ASSERT(trylock());DeleteCriticalSection(&sync);}
	bool trylock(){return !!TryEnterCriticalSection(&sync);}
	void dolock(){EnterCriticalSection(&sync);}
	void unlock(){LeaveCriticalSection(&sync);}
private: CRITICAL_SECTION sync;
};

class autolock
{
public:
	autolock(critical_section* cs) {lock = cs; lock->dolock();}
	~autolock() {ASSERT(lock); lock->unlock();}
private: critical_section* lock;
};

class event
{
public:
	bool initial(bool manual=1, bool init=0)
	{sync=CreateEvent(0,manual,init,0);return NULL!=sync;}
	void destroy(){CloseHandle(sync);sync=NULL;}
	bool pulse(){return !!PulseEvent(sync);}
	bool set(){return !!SetEvent(sync);}
	bool reset(){return !!ResetEvent(sync);}
	bool wait(int t=-1){return WAIT_OBJECT_0 == WaitForSingleObject(sync,t);}
private: HANDLE sync;
};

class semaphore
{
public:
	bool initial(int size, int init=0)
	{sync=CreateSemaphore(0,init,size,0);return NULL!=sync;}
	void destroy(){CloseHandle(sync);}
	bool wait(int t=-1){return WAIT_OBJECT_0 == WaitForSingleObject(sync,t);}
	long release(long n){return ReleaseSemaphore(sync,n,&n)?n:-1;}
private: HANDLE sync;
};

}//namespace


#endif //__CR_SYNC_OBJECT_LOCK_H__